`include "defines.v"
module rdArbiter(
  input clk,
  input rst_n,

  input rd1_addr_valid_i,
  input [`ADDR_W-1:0]rd1_addr_i,
  output rd1_data_valid_o,
  output [127:0]rd1_data_o,

  input  rd2_addr_valid_i,
  input  [`ADDR_W-1:0]rd2_addr_i,
  output rd2_data_valid_o,
  output [127:0]rd2_data_o,

  output  rd_addr_valid_o,
  output  [`ADDR_W-1:0]rd_addr_o,
  input   rd_data_valid_i,
  input   [127:0]rd_data_i
);
parameter IDLE = 3'b001,
          USR1 = 3'b010,
          USR2 = 3'b100;

reg [2:0] cur_state;
reg [2:0] nxt_state;
always@(posedge clk or negedge rst_n)
  if(~rst_n)  
    cur_state <= IDLE;
  else
    cur_state <= nxt_state;

reg handshake ;
always@(posedge clk or negedge rst_n)
  if(~rst_n)
    handshake <= 'd0;
  else 
    handshake <= rd_data_valid_i && rd_addr_valid_o;

always@(*)begin
  case(cur_state)
    IDLE:
      if(rd2_addr_valid_i)
        nxt_state = USR2;
      else if(rd1_addr_valid_i)
        nxt_state = USR1;
      else
        nxt_state = IDLE;
    USR1:
      if(handshake) begin
        if(rd2_addr_valid_i)
          nxt_state = USR2;
        else if(rd1_addr_valid_i)
          nxt_state = USR1;
        else
          nxt_state = IDLE;
      end else
        nxt_state = USR1;
    USR2:
      if(handshake) begin
        if(rd1_addr_valid_i)
          nxt_state = USR1;
        else if(rd2_addr_valid_i)
          nxt_state = USR2;
        else
          nxt_state = IDLE;
      end else
        nxt_state = USR2;
    default:nxt_state = IDLE;
  endcase
end

wire grant_final = (cur_state == USR2);

assign rd_addr_valid_o = grant_final ? rd2_addr_valid_i : rd1_addr_valid_i;
assign rd_addr_o       = grant_final ? rd2_addr_i       : rd1_addr_i      ;

assign rd1_data_o = rd_data_i;
assign rd2_data_o = rd_data_i;

assign rd1_data_valid_o = ~grant_final & rd_data_valid_i;
assign rd2_data_valid_o =  grant_final & rd_data_valid_i;

endmodule